package com.finna.tenant.service.impl;

import com.finna.tenant.dto.*;
import com.finna.tenant.dto.AccountDTO.AccountWithTenantsResponse;
import com.finna.tenant.dto.TenantAccountJoinDTO.*;
import com.finna.tenant.entity.Account;
import com.finna.tenant.entity.Role;
import com.finna.tenant.entity.Tenant;
import com.finna.tenant.entity.TenantAccountJoin;
import com.finna.tenant.mapper.AccountMapper;
import com.finna.tenant.mapper.RoleMapper;
import com.finna.tenant.mapper.TenantAccountJoinMapper;
import com.finna.tenant.mapper.TenantMapper;
import com.finna.tenant.service.TenantAccountJoinService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 租户账号关联服务实现类
 */
@Service
public class TenantAccountJoinServiceImpl implements TenantAccountJoinService {
    
    private static final Logger logger = LoggerFactory.getLogger(TenantAccountJoinServiceImpl.class);
    
    @Autowired
    private TenantAccountJoinMapper tenantAccountJoinMapper;
    
    @Autowired
    private TenantMapper tenantMapper;
    
    @Autowired
    private AccountMapper accountMapper;
    
    @Autowired
    private RoleMapper roleMapper;
    
    @Override
    @Transactional
    public TenantAccountJoinResponse create(TenantAccountJoinCreateRequest request) {
        // 检查租户是否存在
        Tenant tenant = tenantMapper.selectById(request.getTenantId());
        if (tenant == null || tenant.getDeleted()) {
            throw new RuntimeException("租户不存在");
        }
        
        // 检查账号是否存在
        Account account = accountMapper.selectById(request.getAccountId());
        if (account == null) {
            throw new RuntimeException("账号不存在");
        }
        
        // 检查角色是否存在
//        Role role = roleMapper.selectById(request.getRoleId());
//        if (role == null || role.getDeleted()) {
//            throw new RuntimeException("角色不存在");
//        }
        
        // 检查是否已存在关联
        TenantAccountJoin existing = tenantAccountJoinMapper.selectByTenantAndAccount(
            request.getTenantId(), request.getAccountId());
        if (existing != null) {
            throw new RuntimeException("租户和账号的关联已存在");
        }

        // 创建超级管理员关联
//        List<Account> superAdminList = accountMapper.querySuperAdminList();
//        for(Account superAdmin : superAdminList){
//            if(!superAdmin.getId().equals(account.getId())){
//                TenantAccountJoin join = TenantAccountJoin.builder()
//                        .accountId(superAdmin.getAccount())
//                        .tenantId(request.getTenantId())
//                        .roleId(request.getRoleId())
//                        .role(request.getRole())
//                        .createdAt(LocalDateTime.now())
//                        .updatedAt(LocalDateTime.now())
//                        .currentRoleId(request.getRoleId())
//                        .build();
//                tenantAccountJoinMapper.insert(join);
//                logger.info("添加租户账号关联成功: joinId={}, tenantId={}, accountId={}, roleId={}",
//                        join.getId(), request.getTenantId(), request.getAccountId(), request.getRoleId());
//
//                return getById(join.getId());
//            }
//        }


        // 创建关联
        TenantAccountJoin join = TenantAccountJoin.builder()
                .accountId(123456L)
                .tenantId(request.getTenantId())
                .roleId(request.getRoleId())
//                .role(request.getRole() != null ? request.getRole() : role.getName())
                .createdAt(LocalDateTime.now())
                .updatedAt(LocalDateTime.now())
                .currentRoleId(request.getRoleId())
                .build();

        tenantAccountJoinMapper.insert(join);
        
        logger.info("添加租户账号关联成功: joinId={}, tenantId={}, accountId={}, roleId={}", 
                    join.getId(), request.getTenantId(), request.getAccountId(), request.getRoleId());
        
        return getById(join.getId());
    }
    
    @Override
    @Transactional
    public TenantAccountJoinResponse update(Long id, TenantAccountJoinUpdateRequest request) {
        // 检查关联是否存在
        TenantAccountJoin join = tenantAccountJoinMapper.selectById(id);
        if (join == null) {
            throw new RuntimeException("租户账号关联不存在");
        }
        
        // 如果更新角色ID，检查角色是否存在
        if (request.getRoleId() != null) {
            Role role = roleMapper.selectById(request.getRoleId());
            if (role == null || role.getDeleted()) {
                throw new RuntimeException("角色不存在");
            }
            join.setRoleId(request.getRoleId());
            join.setRole(request.getRole() != null ? request.getRole() : role.getName());
            join.setCurrentRoleId(request.getRoleId());
        }
        
        join.setUpdatedAt(LocalDateTime.now());
        tenantAccountJoinMapper.updateById(join);
        
        logger.info("更新租户账号关联成功: joinId={}", id);
        
        return getById(id);
    }
    
    @Override
    @Transactional
    public void delete(Long id) {
        // 检查关联是否存在
        TenantAccountJoin join = tenantAccountJoinMapper.selectById(id);
        if (join == null) {
            throw new RuntimeException("租户账号关联不存在");
        }
        
        tenantAccountJoinMapper.deleteById(id);
        
        logger.info("删除租户账号关联成功: joinId={}", id);
    }
    
    @Override
    public TenantAccountJoinResponse getById(Long id) {
        TenantAccountJoin join = tenantAccountJoinMapper.selectById(id);
        if (join == null) {
            throw new RuntimeException("租户账号关联不存在");
        }
        return TenantAccountJoinResponse.builder()
                .id(join.getId())
                .tenantId(join.getTenantId())
                .accountId(join.getAccountId())
                .roleId(join.getRoleId()).build();
// TODO目前模拟账号关联，所以这里直接返回
//        return convertToResponse(join);
    }
    
    @Override
    public PageResponse<TenantAccountJoinResponse> list(TenantAccountJoinListRequest request) {
        // 构建查询参数
        Map<String, Object> params = new HashMap<>();
        if (request.getTenantId() != null) {
            params.put("tenantId", request.getTenantId());
        }
        if (request.getAccountId() != null) {
            params.put("accountId", request.getAccountId());
        }
        if (request.getRoleId() != null) {
            params.put("roleId", request.getRoleId());
        }
        
        // 分页参数
        Integer page = request.getPage() != null ? request.getPage() : 1;
        Integer pageSize = request.getPageSize() != null ? request.getPageSize() : 10;
        if (pageSize > 100) {
            pageSize = 100;
        }
        
        // 使用PageHelper进行分页
        PageHelper.startPage(page, pageSize);
        List<Map<String, Object>> results = tenantAccountJoinMapper.selectListWithDetails(params);
        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(results);
        
        // 转换为Response对象
        List<TenantAccountJoinResponse> responses = pageInfo.getList().stream()
            .map(this::convertMapToResponse)
            .collect(Collectors.toList());
        
        return new PageResponse<>(responses, pageInfo.getTotal(), page, pageSize);
    }
    
    @Override
    public TenantWithAccountsResponse getTenantAccounts(Long tenantId) {
        // 检查租户是否存在
        Tenant tenant = tenantMapper.selectById(tenantId);
        if (tenant == null || tenant.getDeleted()) {
            throw new RuntimeException("租户不存在");
        }
        
        // 查询租户的账号列表
        List<Map<String, Object>> accountMaps = tenantAccountJoinMapper.selectAccountsByTenantId(tenantId);
        
        // 构建响应对象
        TenantWithAccountsResponse response = new TenantWithAccountsResponse();
        response.setId(tenant.getId());
        response.setTenantName(tenant.getTenantName());
        response.setTenantAvatar(tenant.getTenantCode());
        response.setIsPublic(tenant.getIsPublic());
        response.setAccountCount(accountMaps.size());
        response.setCreatedAt(tenant.getCreateTime());
        
        // 转换账号列表
        List<TenantWithAccountsResponse.AccountInTenant> accounts = accountMaps.stream()
            .map(map -> {
                TenantWithAccountsResponse.AccountInTenant account = new TenantWithAccountsResponse.AccountInTenant();
                account.setAccountId(getLong(map, "account_id"));
                account.setAccountName(getString(map, "account_name"));
                account.setAccountAvatar(getString(map, "account_avatar"));
                account.setRoleId(getLong(map, "role_id"));
                account.setRoleName(getString(map, "role_name"));
                account.setRole(getString(map, "role"));
                account.setJoinedAt(getLocalDateTime(map, "joined_at"));
                return account;
            })
            .collect(Collectors.toList());
        
        response.setAccounts(accounts);
        
        return response;
    }
    
    @Override
    public AccountWithTenantsResponse getAccountTenants(Long accountId) {
        // 检查账号是否存在
        com.finna.tenant.entity.Account account = accountMapper.selectById(accountId);
        if (account == null) {
            throw new RuntimeException("账号不存在");
        }
        
        // 查询账号所属的租户列表
        List<Map<String, Object>> tenantMaps = tenantAccountJoinMapper.selectTenantsByAccountId(accountId);
        
        // 构建响应对象
        AccountWithTenantsResponse response = new AccountWithTenantsResponse();
        response.setId(account.getId());
        response.setAccountName(account.getName());
        response.setAccountAvatar(account.getAvatar());
        response.setEmail(account.getEmail());
        response.setTenantCount(tenantMaps.size());
        response.setCreatedAt(account.getCreateTime());
        
        // 转换租户列表
        List<AccountWithTenantsResponse.TenantForAccount> tenants = tenantMaps.stream()
            .map(map -> {
                AccountWithTenantsResponse.TenantForAccount tenant = new AccountWithTenantsResponse.TenantForAccount();
                tenant.setTenantId(getLong(map, "tenant_id"));
                tenant.setTenantName(getString(map, "tenant_name"));
                tenant.setTenantAvatar(getString(map, "tenant_avatar"));
                tenant.setIsPublic(getBoolean(map, "is_public"));
                tenant.setRoleId(getLong(map, "role_id"));
                tenant.setRoleName(getString(map, "role_name"));
                tenant.setRole(getString(map, "role"));
                tenant.setJoinedAt(getLocalDateTime(map, "joined_at"));
                return tenant;
            })
            .collect(Collectors.toList());
        
        response.setTenants(tenants);
        
        return response;
    }
    
    @Override
    public TenantAccountJoinResponse getTenantAccountRole(Long tenantId, Long accountId) {
        TenantAccountJoin join = tenantAccountJoinMapper.selectByTenantAndAccount(tenantId, accountId);
        if (join == null) {
            throw new RuntimeException("租户账号关联不存在");
        }
        
        return convertToResponse(join);
    }

    @Override
    public void deleteByTenantId(Long id) {
        //TODO
    }

    /**
     * 转换实体为响应对象
     */
    private TenantAccountJoinResponse convertToResponse(TenantAccountJoin join) {
        TenantAccountJoinResponse response = new TenantAccountJoinResponse();
        response.setId(join.getId());
        response.setTenantId(join.getTenantId());
        response.setAccountId(join.getAccountId());
        response.setRoleId(join.getRoleId());
        response.setRole(join.getRole());
        response.setCreatedAt(join.getCreatedAt());
        response.setUpdatedAt(join.getUpdatedAt());
        
        // 查询关联信息
        try {
            Tenant tenant = tenantMapper.selectById(join.getTenantId());
            if (tenant != null) {
                response.setTenantName(tenant.getTenantName());
                response.setTenantAvatar(tenant.getTenantCode());
                response.setIsPublic(tenant.getIsPublic());
            }
        } catch (Exception e) {
            logger.warn("查询租户信息失败: tenantId={}", join.getTenantId(), e);
        }
        
        try {
            com.finna.tenant.entity.Account account = accountMapper.selectById(join.getAccountId());
            if (account != null) {
                response.setAccountName(account.getName());
                response.setAccountAvatar(account.getAvatar());
            }
        } catch (Exception e) {
            logger.warn("查询账号信息失败: accountId={}", join.getAccountId(), e);
        }
        
        try {
            Role role = roleMapper.selectById(join.getRoleId());
            if (role != null) {
                response.setRoleName(role.getName());
                response.setMetaInfo(role.getMetaInfo());
            }
        } catch (Exception e) {
            logger.warn("查询角色信息失败: roleId={}", join.getRoleId(), e);
        }
        
        return response;
    }
    
    /**
     * 从Map转换为响应对象
     */
    private TenantAccountJoinResponse convertMapToResponse(Map<String, Object> map) {
        TenantAccountJoinResponse response = new TenantAccountJoinResponse();
        response.setId(getLong(map, "id"));
        response.setTenantId(getLong(map, "tenant_id"));
        response.setAccountId(getLong(map, "account_id"));
        response.setRoleId(getLong(map, "role_id"));
        response.setRole(getString(map, "role"));
        response.setCreatedAt(getLocalDateTime(map, "created_at"));
        response.setUpdatedAt(getLocalDateTime(map, "updated_at"));
        response.setTenantName(getString(map, "tenant_name"));
        response.setTenantAvatar(getString(map, "tenant_avatar"));
        response.setIsPublic(getBoolean(map, "is_public"));
        response.setAccountName(getString(map, "account_name"));
        response.setAccountAvatar(getString(map, "account_avatar"));
        response.setRoleName(getString(map, "role_name"));
        response.setMetaInfo(getString(map, "meta_info"));
        return response;
    }
    
    // 辅助方法
    private Long getLong(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value == null) return null;
        if (value instanceof Long) return (Long) value;
        if (value instanceof Integer) return ((Integer) value).longValue();
        if (value instanceof String) return Long.parseLong((String) value);
        return null;
    }
    
    private String getString(Map<String, Object> map, String key) {
        Object value = map.get(key);
        return value != null ? value.toString() : null;
    }
    
    private Boolean getBoolean(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value == null) return null;
        if (value instanceof Boolean) return (Boolean) value;
        if (value instanceof Integer) return ((Integer) value) != 0;
        if (value instanceof String) return Boolean.parseBoolean((String) value);
        return null;
    }
    
    private LocalDateTime getLocalDateTime(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value == null) return null;
        if (value instanceof LocalDateTime) return (LocalDateTime) value;
        if (value instanceof java.sql.Timestamp) {
            return ((java.sql.Timestamp) value).toLocalDateTime();
        }
        return null;
    }
}
